<template>
  <div class="system-bg">
    <el-card class="user-card" shadow="hover">
      <div slot="header" class="card-header-vertical">
        <div class="header-title">角色管理</div>
        <div class="header-btn-group right">
          <el-button class="add-btn" type="primary" @click="onShowAdd">
            <i class="el-icon-plus"></i> 新增角色
          </el-button>
          <el-button class="delete-btn" type="danger" :disabled="!multipleSelection.length" @click="batchRemove">
            <i class="el-icon-delete"></i> 批量删除
          </el-button>
          <el-button class="menu-btn" @click="setMenusBatch" :disabled="!multipleSelection.length">
            <i class="el-icon-menu"></i> 批量分配菜单
          </el-button>
        </div>
      </div>
      <el-form :inline="true" :model="searchForm" class="search-bar">
        <el-form-item label="角色名称">
          <el-input v-model="searchForm.name" placeholder="角色名称" size="small" />
        </el-form-item>
        <el-form-item label="状态">
          <el-select v-model="searchForm.status" placeholder="全部" size="small">
            <el-option label="全部" :value="''" />
            <el-option label="启用" :value="1" />
            <el-option label="禁用" :value="0" />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" size="small" @click="onSearch">搜索</el-button>
        </el-form-item>
        <el-form-item>
          <el-button size="small" @click="onReset">重置</el-button>
        </el-form-item>
      </el-form>
      <el-table
        ref="roleTable"
        :data="list"
        style="width:100%"
        class="user-table"
        highlight-current-row
        @selection-change="handleSelectionChange"
        @row-click="handleRowClick"
      >
        <el-table-column type="selection" width="50" />
        <el-table-column prop="id" label="ID" width="70" align="center" />
        <el-table-column prop="name" label="角色名称" width="150" />
        <el-table-column prop="code" label="角色编码" width="120" />
        <el-table-column prop="description" label="描述" />
        <el-table-column prop="status" label="状态" width="90">
          <template slot-scope="scope">
            <el-tag :type="scope.row.status === 1 ? 'success' : 'danger'">
              {{ scope.row.status === 1 ? '启用' : '禁用' }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="createdAt" label="创建时间" width="160" />
        <el-table-column label="操作" width="200" align="center">
          <template slot-scope="scope">
            <el-button size="mini" class="edit-btn" @click="edit(scope.row)">编辑</el-button>
            <!-- <el-button size="mini" class="menu-btn" @click="setMenus(scope.row)">分配菜单</el-button> -->
            <el-button size="mini" class="delete-btn" type="danger" @click="remove(scope.row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
      <el-pagination
        :total="total"
        :page-size="size"
        :current-page="current"
        @current-change="load"
        @size-change="handleSizeChange"
        layout="total, prev, pager, next, jumper, ->, sizes"
        :page-sizes="[10, 20, 50, 100]"
        class="user-pagination"
      />
    </el-card>
    
    <!-- 新增/编辑角色弹窗 -->
    <el-dialog :visible.sync="showDialog" :title="dialogTitle" class="fade-dialog custom-dialog" :close-on-click-modal="false" width="500px">
      <el-form :model="form" label-width="90px" class="dialog-form">
        <el-form-item label="角色名称">
          <el-input v-model="form.name" />
        </el-form-item>
        <el-form-item label="角色编码">
          <el-input v-model="form.code" :disabled="isEdit" />
        </el-form-item>
        <el-form-item label="角色描述">
          <el-input v-model="form.description" type="textarea" :rows="3" />
        </el-form-item>
        <el-form-item label="状态">
          <el-select v-model="form.status" placeholder="请选择状态" style="width: 100%;">
            <el-option label="启用" :value="1" />
            <el-option label="禁用" :value="0" />
          </el-select>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="showDialog=false">取消</el-button>
        <el-button type="primary" @click="save">确定</el-button>
      </div>
    </el-dialog>
    
    <!-- 设置菜单弹窗 -->
    <el-dialog :visible.sync="showMenuDialog" title="设置角色菜单" class="fade-dialog custom-dialog" :close-on-click-modal="false" width="600px">
      <el-form label-width="90px">
        <el-form-item label="角色">
          <span>{{ currentRole ? currentRole.name : '' }}</span>
        </el-form-item>
        <el-form-item label="菜单权限">
          <div v-if="!currentRole" style="color:#888;font-size:13px;margin-bottom:6px;">
            已勾选为所有选中角色的菜单权限（合并去重）
          </div>
          <el-tree
            ref="menuTree"
            :data="menuTree"
            :props="menuProps"
            show-checkbox
            node-key="id"
            :default-checked-keys="selectedMenus"
            :default-expanded-keys="expandedKeys"
          />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="showMenuDialog=false">取消</el-button>
        <el-button type="primary" @click="saveMenus">确定</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { getRoleList, addRole, updateRole, deleteRole, getMenusByRole, setRoleMenus } from '@/api/role';
import { getMenuList } from '@/api/menu';

export default {
  name: 'SystemRole',
  data() {
    return {
      list: [],
      total: 0,
      size: 10,
      current: 1,
      showDialog: false,
      showMenuDialog: false,
      isEdit: false,
      dialogTitle: '新增角色',
      form: {
        name: '',
        code: '',
        description: '',
        status: 1
      },
      menuTree: [],
      selectedMenus: [],
      expandedKeys: [],
      currentRole: null,
      menuProps: {
        children: 'children',
        label: 'name'
      },
      searchForm: {
        name: '',
        status: ''
      },
      multipleSelection: [],
      currentRow: null,
    };
  },
  created() {
    this.load();
    this.loadMenus();
  },
  methods: {
    async load(page = 1) {
      this.current = page;
      const params = {
        page,
        size: this.size,
        ...this.searchForm
      };
      const data = await getRoleList(params);
      this.list = data.records;
      this.total = data.total;
      this.size = data.size;
      this.current = data.current;
    },
    handleSizeChange(size) {
      this.size = size;
      this.load(1);
    },
    async loadMenus() {
      try {
        const data = await getMenuList({ page: 1, size: 1000 });
        this.menuTree = this.buildMenuTree(data.records || []);
        this.expandedKeys = this.getExpandedKeys(this.menuTree);
      } catch (error) {
        console.error('加载菜单列表失败:', error);
        this.$message.error('加载菜单列表失败');
      }
    },
    buildMenuTree(menus) {
      const menuMap = {};
      const tree = [];
      
      // 创建菜单映射
      menus.forEach(menu => {
        menuMap[menu.id] = { ...menu, children: [] };
      });
      
      // 构建树结构
      menus.forEach(menu => {
        if (menu.parentId === 0) {
          tree.push(menuMap[menu.id]);
        } else {
          const parent = menuMap[menu.parentId];
          if (parent) {
            parent.children.push(menuMap[menu.id]);
          }
        }
      });
      
      return tree;
    },
    getExpandedKeys(tree) {
      const keys = [];
      const traverse = (nodes) => {
        nodes.forEach(node => {
          if (node.children && node.children.length > 0) {
            keys.push(node.id);
            traverse(node.children);
          }
        });
      };
      traverse(tree);
      return keys;
    },
    onShowAdd() {
      this.isEdit = false;
      this.dialogTitle = '新增角色';
      this.form = {
        name: '',
        code: '',
        description: '',
        status: 1
      };
      this.showDialog = true;
    },
    edit(row) {
      this.isEdit = true;
      this.dialogTitle = '编辑角色';
      this.form = { ...row };
      this.showDialog = true;
    },
    async save() {
      try {
        if (this.isEdit) {
          await updateRole(this.form.id, this.form);
          this.$message.success('角色更新成功');
        } else {
          await addRole(this.form);
          this.$message.success('角色添加成功');
        }
        this.showDialog = false;
        this.load();
      } catch (error) {
        console.error('保存角色失败:', error);
        this.$message.error('保存角色失败');
      }
    },
    async remove(row) {
      try {
        await this.$confirm('确定要删除该角色吗？', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        });
        await deleteRole(row.id);
        this.$message.success('角色删除成功');
        this.load();
      } catch (error) {
        if (error !== 'cancel') {
          console.error('删除角色失败:', error);
          this.$message.error('删除角色失败');
        }
      }
    },
    // 修正：分配菜单时，确保菜单树正确选中角色已有的菜单
    async setMenus(row) {
      this.currentRole = row;
      this.selectedMenus = [];
      try {
        const menus = await getMenusByRole(row.id);
        // 强制转字符串，防止类型不一致
        this.selectedMenus = menus.map(menu => String(menu.id));
        this.showMenuDialog = true;
        // 等待弹窗渲染和菜单树渲染完成后再设置选中
        this.$nextTick(() => {
          // 需要再等一帧，确保 el-tree 已经渲染
          setTimeout(() => {
            if (this.$refs.menuTree) {
              // 先清空所有选中
              this.$refs.menuTree.setCheckedKeys([]);
              // 再设置选中
              this.$refs.menuTree.setCheckedKeys(this.selectedMenus);
            }
          }, 100);
        });
      } catch (error) {
        console.error('获取角色菜单失败:', error);
        this.$message.error('获取角色菜单失败');
      }
    },
    async saveMenus() {
      try {
        const checkedKeys = this.$refs.menuTree.getCheckedKeys();
        const halfCheckedKeys = this.$refs.menuTree.getHalfCheckedKeys();
        const allKeys = [...checkedKeys, ...halfCheckedKeys];
        if (this.currentRole) {
          // 单角色
          await setRoleMenus(this.currentRole.id, allKeys);
        } else {
          // 批量
          for (const role of this.multipleSelection) {
            await setRoleMenus(role.id, allKeys);
          }
        }
        this.$message.success('菜单设置成功');
        this.showMenuDialog = false;
      } catch (error) {
        console.error('设置角色菜单失败:', error);
        this.$message.error('设置角色菜单失败');
      }
    },
    onSearch() {
      this.current = 1;
      this.load();
    },
    onReset() {
      this.searchForm = {
        name: '',
        status: ''
      };
      this.load();
    },
    handleSelectionChange(val) {
      this.multipleSelection = val;
    },
    handleRowClick(row) {
      this.currentRow = row;
      this.$refs.roleTable.clearSelection();
      this.$refs.roleTable.toggleRowSelection(row, true);
    },
    async batchRemove() {
      if (!this.multipleSelection.length) {
        this.$message.warning('请选择要删除的角色');
        return;
      }
      try {
        await this.$confirm('确定要批量删除选中的角色吗？', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        });
        const ids = this.multipleSelection.map(item => item.id);
        await deleteRole(ids);
        this.$message.success('角色批量删除成功');
        this.load();
      } catch (error) {
        if (error !== 'cancel') {
          console.error('批量删除角色失败:', error);
          this.$message.error('批量删除角色失败');
        }
      }
    },
    async setMenusBatch() {
      if (!this.multipleSelection.length) {
        this.$message.warning('请选择要分配菜单的角色');
        return;
      }
      // 合并所有选中角色的菜单ID（去重）
      let allMenuIds = new Set();
      for (const role of this.multipleSelection) {
        const menus = await getMenusByRole(role.id);
        menus.forEach(menu => allMenuIds.add(String(menu.id)));
      }
      this.selectedMenus = Array.from(allMenuIds);
      this.currentRole = null; // 批量操作不显示单一角色名
      this.showMenuDialog = true;
      this.$nextTick(() => {
        setTimeout(() => {
          if (this.$refs.menuTree) {
            this.$refs.menuTree.setCheckedKeys([]);
            this.$refs.menuTree.setCheckedKeys(this.selectedMenus);
          }
        }, 100);
      });
    }
  }
};
</script>

<style scoped>
.system-bg {
  min-height: 80vh;
  background: linear-gradient(135deg, #f4f6fa 60%, #e0e7ff 100%);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 48px 0;
  animation: fadeIn 0.8s;
}
@keyframes fadeIn {
  from { opacity: 0; transform: translateY(30px);}
  to { opacity: 1; transform: none;}
}
.user-card {
  width: 1100px;
  border-radius: 18px;
  box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.10);
  background: rgba(255,255,255,0.95);
  transition: box-shadow 0.3s;
}
.card-header-vertical {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  padding-bottom: 8px;
}
.header-title {
  font-size: 22px;
  font-weight: bold;
  margin-bottom: 10px;
  text-align: left;
}
.header-btn-group {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  background: none;
  border-radius: 0;
  padding: 0;
  box-shadow: none;
}
.header-btn-group.right {
  justify-content: flex-end;
}
.header-btn-group .el-button {
  margin-right: 8px;
  height: 34px;
  font-size: 15px;
  padding: 0 18px;
  display: flex;
  align-items: center;
}
.header-btn-group .el-button:last-child {
  margin-right: 0;
}
.add-btn {
  background: linear-gradient(90deg, #6a82fb 0%, #fc5c7d 100%);
  border: none;
  color: #fff;
  font-weight: bold;
}
.add-btn:hover {
  background: linear-gradient(90deg, #fc5c7d 0%, #6a82fb 100%);
}
.user-table {
  border-radius: 10px;
  overflow: hidden;
  margin-bottom: 18px;
}
.user-table ::v-deep .el-table__row:hover {
  background: #f0f7ff !important;
  transition: background 0.2s;
}
.edit-btn {
  background: #fff;
  border: 1px solid #6a82fb;
  color: #6a82fb;
  margin-right: 8px;
  transition: all 0.2s;
}
.edit-btn:hover {
  background: #6a82fb;
  color: #fff;
}
.delete-btn {
  background: #fff;
  border: 1px solid #fc5c7d;
  color: #fc5c7d;
  transition: all 0.2s;
}
.delete-btn:hover {
  background: #fc5c7d;
  color: #fff;
}
.user-pagination {
  margin-top: 18px;
  text-align: right;
}
.user-pagination ::v-deep .el-pager li {
  border-radius: 6px;
  transition: background 0.2s;
}
.user-pagination ::v-deep .el-pager li.active {
  background: #6a82fb;
  color: #fff;
}
.fade-dialog ::v-deep .el-dialog__wrapper {
  animation: fadeIn 0.4s;
}
.custom-dialog ::v-deep .el-dialog {
  border-radius: 16px;
  box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.18);
  background: #fafdff;
  padding-bottom: 0;
}
.dialog-form {
  padding: 12px 0 0 0;
}
.dialog-form ::v-deep .el-form-item {
  margin-bottom: 22px;
}
.dialog-footer {
  text-align: right;
  padding: 8px 0 8px 0;
}
.dialog-footer .el-button {
  min-width: 80px;
  border-radius: 6px;
  font-weight: 500;
  margin-left: 8px;
}
.dialog-footer .el-button--primary {
  background: linear-gradient(90deg, #6a82fb 0%, #fc5c7d 100%);
  border: none;
}
.dialog-footer .el-button--primary:hover {
  background: linear-gradient(90deg, #fc5c7d 0%, #6a82fb 100%);
}
.search-bar {
  margin-bottom: 20px;
  padding: 20px;
  background: transparent;
  border-radius: 8px;
  border: none;
}
</style> 